package hasher

import (
	"bufio"
	"crypto/hmac"
	"crypto/sha512"
	"encoding/hex"
	"errors"
	"io"
	"os"

	"gitee.com/gousing/helper/internal"
)

// Sha512 （128位）小写Hex字符串
func Sha512(in string) string {
	return hex.EncodeToString(Sha512Bytes(internal.StringToBytes(in)))
}

// Sha512Bytes （64位）Hex字节数组
func Sha512Bytes(in []byte) []byte {
	if len(in) == 0 {
		in = []byte{}
	}
	h := sha512.Sum512(in)
	return h[:]
}

// Sha512File （128位）小写Hex字符串
func Sha512File(filePath string) (string, error) {
	data, err := Sha512FileBytes(filePath)
	if err != nil {
		return "", err
	}
	return hex.EncodeToString(data), nil
}

// Sha512FileBytes （64位）Hex字节数组
func Sha512FileBytes(filePath string) ([]byte, error) {
	if filePath == "" {
		return []byte{}, errors.New("Sha512FileBytes: filePath is empty")
	}
	file, err := os.Open(filePath)
	if err != nil {
		return []byte{}, err
	}
	defer file.Close()
	h := sha512.New()
	reader := bufio.NewReader(file)
	buf := make([]byte, 4096) // 4KB的缓冲区
	for {
		n, err := reader.Read(buf)
		if err != nil && err != io.EOF {
			return []byte{}, err
		}
		if n == 0 {
			break
		}
		h.Write(buf[:n])
	}
	return h.Sum(nil), nil
}

// Sha512Hmac （128位）小写Hex字符串
func Sha512Hmac(in, key string) string {
	return hex.EncodeToString(Sha512HmacBytes(internal.StringToBytes(in), internal.StringToBytes(key)))
}

// Sha512HmacBytes （64位）Hex字节数组
func Sha512HmacBytes(in, key []byte) []byte {
	if len(in) == 0 {
		in = []byte{}
	}
	if len(key) == 0 {
		panic("Sha512HmacByte: key is empty")
	}
	hash := hmac.New(sha512.New, key)
	hash.Write(in)
	return hash.Sum(nil)
}

// Sha512HmacFile （128位）小写Hex字符串
func Sha512HmacFile(filePath, key string) (string, error) {
	data, err := Sha512HmacFileBytes(filePath, internal.StringToBytes(key))
	if err != nil {
		return "", err
	}
	return hex.EncodeToString(data), nil
}

// Sha512HmacFileBytes （64位）Hex字节数组
func Sha512HmacFileBytes(filePath string, key []byte) ([]byte, error) {
	if filePath == "" {
		return []byte{}, errors.New("Sha512HmacFileBytes: filePath is empty")
	}
	if len(key) == 0 {
		return []byte{}, errors.New("Sha512HmacFileBytes: key is empty")
	}
	file, err := os.Open(filePath)
	if err != nil {
		return []byte{}, err
	}
	defer file.Close()
	h := hmac.New(sha512.New, key)
	reader := bufio.NewReader(file)
	buf := make([]byte, 4096) // 4KB的缓冲区
	for {
		n, err := reader.Read(buf)
		if err != nil && err != io.EOF {
			return []byte{}, err
		}
		if n == 0 {
			break
		}
		h.Write(buf[:n])
	}
	return h.Sum(nil), nil
}
